package com.ruoyi.training.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.constant.training.CurriculumConstants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.training.domain.*;
import com.ruoyi.training.domain.req.CommitPaperProcessReq;
import com.ruoyi.training.domain.req.PlanPaperReq;
import com.ruoyi.training.domain.vo.OptionVO;
import com.ruoyi.training.domain.vo.QuestionVO;
import com.ruoyi.training.domain.vo.TrainPlanPaperVO;
import com.ruoyi.training.domain.vo.TrainPlanPaperVO_map;
import com.ruoyi.training.mapper.*;
import com.ruoyi.training.service.ITrainPlanPaperService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 培训计划试卷Service业务层处理
 *
 * @author wng
 * @date 2024-08-04
 */
@Service
public class TrainPlanPaperServiceImpl implements ITrainPlanPaperService {
    @Resource
    private TrainPlanPaperMapper trainPlanPaperMapper;
    @Resource
    private TrainPlanMapper trainPlanMapper;
    @Resource
    private TrainPlanPaperQuestionMapper trainPlanPaperQuestionMapper;
    @Resource
    private ExamResMapper examResMapper;
    @Resource
    private ExamRecordMapper examRecordMapper;
    @Resource
    private RedisCache redisCache;

    /**
     * 查询培训计划试卷
     *
     * @param id 培训计划试卷主键
     * @return 培训计划试卷
     */
    @Override
    public TrainPlanPaperVO selectTrainPlanPaperById(Long id) {
        TrainPlanPaper planPaper = trainPlanPaperMapper.selectTrainPlanPaperById(id);
//        List<TrainPlanPaperQuestion> paperQuestions = trainPlanPaperQuestionMapper.selectTrainPlanPaperQuestionList(new TrainPlanPaperQuestion() {{
//            setPaperId(id);
//        }});
//        planPaper.getParams().put("paperQuestions", paperQuestions);

        return getTrainPlanPaperVO(planPaper);
    }

    /**
     * 根据培训计划查询试卷详情
     */
    @Override
    public TrainPlanPaperVO planPaper(PlanPaperReq req) {
        List<TrainPlanPaper> trainPlanPapers = trainPlanPaperMapper.selectTrainPlanPaperList(new TrainPlanPaper() {{
            setPlanId(req.getPlanId());
        }});
        List<TrainPlanPaperVO> trainPlanPaperVOS = new ArrayList<>(10);
        trainPlanPapers.forEach(item -> {
            trainPlanPaperVOS.add(getTrainPlanPaperVO(item));
        });

        TrainPlanPaperVO paperVO = trainPlanPaperVOS.get(0);

        //将试卷存入redis key值为：培训计划id-试卷id-用户id
        String key = "paper:user:" + paperVO.getPlanId() + "-" + paperVO.getId() + "-" + req.getUserId();
        if (!redisCache.hasKey(key)) {
            redisCache.setCacheObject(key, paperVO, 60 * 60 * 24 * 5, TimeUnit.SECONDS);
        }

        return trainPlanPaperVOS.get(0);
    }

    private TrainPlanPaperVO getTrainPlanPaperVO(TrainPlanPaper item) {
        TrainPlanPaperVO paperVO = new TrainPlanPaperVO(item.getId(), item.getPlanId(), item.getTitle());

        List<TrainPlanPaperQuestion> paperQuestions = trainPlanPaperQuestionMapper.selectTrainPlanPaperQuestionList(new TrainPlanPaperQuestion() {{
            setPaperId(item.getId());
        }});

        List<QuestionVO> questionVOS = new ArrayList<>(10);
        //格式化选项
        paperQuestions.forEach(question -> {

            QuestionVO questionVO = new QuestionVO(question.getId(), question.getPaperId(), question.getProblem(), question.getTopicType(), question.getScore());

            List<ExamQuestionOption> options = JSON.parseArray(question.getOptionJson(), ExamQuestionOption.class);

            List<OptionVO> optionVOS = new ArrayList<>(10);

            options.forEach(option -> {
                OptionVO optionVO = new OptionVO(option.getId(), option.getQuestionId(), option.getOption(), option.getContent());
                optionVOS.add(optionVO);
            });
            questionVO.setOptions(optionVOS);
            questionVOS.add(questionVO);
        });
        paperVO.setQuestions(questionVOS);

        Map<CurriculumConstants.TopicTypeEnum, List<QuestionVO>> collect = paperVO.getQuestions().stream().collect(Collectors.groupingBy(QuestionVO::getTopicType));
        List<TrainPlanPaperVO_map> questions_map = new ArrayList<>();
        collect.forEach((topicType, questions) -> {
            TrainPlanPaperVO_map paperVO_map = new TrainPlanPaperVO_map();
            paperVO_map.setTitle(topicType.getTypeName());
            paperVO_map.setQuestions(questions);
            questions_map.add(paperVO_map);
        });
        paperVO.setQuestions_map(questions_map);
        paperVO.setQuestions(null);

        return paperVO;
    }

    /**
     * 查询培训计划试卷列表
     *
     * @param trainPlanPaper 培训计划试卷
     * @return 培训计划试卷
     */
    @Override
    public List<TrainPlanPaper> selectTrainPlanPaperList(TrainPlanPaper trainPlanPaper) {

        if (trainPlanPaper.getParams().containsKey("createTimeStart") && trainPlanPaper.getParams().containsKey("createTimeEnd")) {
            if (trainPlanPaper.getParams().get("createTimeStart") != null && !"".equals(trainPlanPaper.getParams().get("createTimeStart"))
                    && trainPlanPaper.getParams().get("createTimeEnd") != null && !"".equals(trainPlanPaper.getParams().get("createTimeEnd"))) {
                trainPlanPaper.getParams().put("createTimeStart", trainPlanPaper.getParams().get("createTimeStart") + " 00:00:00");
                trainPlanPaper.getParams().put("createTimeEnd", trainPlanPaper.getParams().get("createTimeEnd") + " 23:59:59");
            }

        }
        List<TrainPlanPaper> trainPlanPapers = trainPlanPaperMapper.selectTrainPlanPaperList(trainPlanPaper);
        trainPlanPapers.forEach(item -> {
            TrainPlan trainPlan = trainPlanMapper.selectTrainPlanById(item.getPlanId());
            if (trainPlan != null) {
                item.getParams().put("planTitle", trainPlan.getTitle());
                item.setPlanTitle(trainPlan.getTitle());
            }
        });
        return trainPlanPapers;
    }

    /**
     * 新增培训计划试卷
     *
     * @param trainPlanPaper 培训计划试卷
     * @return 结果
     */
    @Override
    public int insertTrainPlanPaper(TrainPlanPaper trainPlanPaper) {
        trainPlanPaper.setCreateTime(DateUtils.getNowDate());
        return trainPlanPaperMapper.insertTrainPlanPaper(trainPlanPaper);
    }

    /**
     * 修改培训计划试卷
     *
     * @param trainPlanPaper 培训计划试卷
     * @return 结果
     */
    @Override
    public int updateTrainPlanPaper(TrainPlanPaper trainPlanPaper) {
        trainPlanPaper.setUpdateTime(DateUtils.getNowDate());
        return trainPlanPaperMapper.updateTrainPlanPaper(trainPlanPaper);
    }

    /**
     * 批量删除培训计划试卷
     *
     * @param ids 需要删除的培训计划试卷主键
     * @return 结果
     */
    @Override
    public int deleteTrainPlanPaperByIds(Long[] ids) {
        return trainPlanPaperMapper.deleteTrainPlanPaperByIds(ids);
    }

    /**
     * 删除培训计划试卷信息
     *
     * @param id 培训计划试卷主键
     * @return 结果
     */
    @Override
    public int deleteTrainPlanPaperById(Long id) {
        return trainPlanPaperMapper.deleteTrainPlanPaperById(id);
    }

    /**
     * 做一题保存一题,实时保存做题进度
     */
    @Override
    public void commitPaperProcess(CommitPaperProcessReq req) {

        String key = "paper:user:" + req.getPlanId() + "-" + req.getPaperId() + "-" + req.getUserId();
        TrainPlanPaperVO paperVO = redisCache.getCacheObject(key);
        paperVO.getQuestions_map().forEach(item -> {
            item.getQuestions().stream().filter(s -> s.getId().equals(req.getQuestionId())).forEach(item_in -> {
                item_in.setAnswer(req.getAnswer());
            });
        });

        redisCache.setCacheObject(key, paperVO, 60 * 60 * 24 * 5, TimeUnit.SECONDS);

    }

    /**
     * 提交考试
     */
    @Override
    public void commitExam(CommitPaperProcessReq req) {
        String key = "paper:user:" + req.getPlanId() + "-" + req.getPaperId() + "-" + req.getUserId();
        TrainPlanPaperVO paperVO = redisCache.getCacheObject(key);

        //查询试卷下所有题目并转为map，questionId做为key值
        Map<Long, TrainPlanPaperQuestion> paperQuestionMap = trainPlanPaperQuestionMapper.selectTrainPlanPaperQuestionList(new TrainPlanPaperQuestion() {{
            setPaperId(req.getPaperId());
        }}).stream().collect(Collectors.toMap(TrainPlanPaperQuestion::getId, planPaper -> planPaper));

        BigDecimal score = BigDecimal.ZERO;
        //计算分数
        for (TrainPlanPaperVO_map item : paperVO.getQuestions_map()) {
            for (QuestionVO item_in : item.getQuestions()) {
                TrainPlanPaperQuestion paperQuestion = paperQuestionMap.get(item_in.getId());
                item_in.setCorrect(paperQuestion.getAnswer().equals(item_in.getAnswer()));
                item_in.setCorrectAnswer(paperQuestion.getAnswer());

                if (item_in.isCorrect()) {
                    score = score.add(item_in.getScore());
                }
            }
        }

        Date date = new Date();
        //持久化做题记录
        List<ExamRes> examRes_search = examResMapper.selectExamResList(new ExamRes() {{
            setUserId(req.getUserId());
            setPaperId(req.getPaperId());
            setPlanId(req.getPlanId());
        }});

        if (examRes_search.isEmpty()) {
            ExamRes examRes = new ExamRes(req.getUserId(), req.getPaperId(), req.getPlanId(), JSON.toJSONString(paperVO));
            examRes.setCreateTime(date);
            examResMapper.insertExamRes(examRes);
        } else {
            examRes_search.forEach(item -> {
                item.setExamRes(JSON.toJSONString(paperVO));
                examResMapper.updateExamRes(item);
            });
        }


        //修改培训记录
        List<ExamRecord> examRecords = examRecordMapper.selectExamRecordList(new ExamRecord() {{
            setPlanId(req.getPlanId());
            setUserId(req.getUserId());
        }});
        if (!examRecords.isEmpty()) {
            for (ExamRecord item : examRecords) {
                item.setScore(score);
                item.setUpdateTime(date);
                examRecordMapper.updateExamRecord(item);
            }
        }
    }

}
